<template>
  <div>
    <common-dialog ref="dialog" width="700px" :title="title" :inDialog="inDialog" :init-base-data-func="initBaseData"
      @closed="onClosed" @close="onClose">
      <common-form ref="form" :data="data" :rules="rules">
        <el-divider>角色信息</el-divider>
        <el-form-item label="角色名称" prop="name">
          <el-input v-model="data.name" placeholder="填写角色名称"></el-input>
        </el-form-item>
        <el-form-item label="角色备注" prop="remarks">
          <el-input v-model="data.remarks" placeholder="填写角色备注"></el-input>
        </el-form-item>
        <el-form-item label="菜单权限">
          <el-table ref="table" :data="menuPermissionTreeData" :select-on-indeterminate="false"
            v-loading="menuPermissionLoading" border stripe default-expand-all row-key="id">
            <el-table-column width="40" type="index" align="center">
              <template #header>
                <el-checkbox :value="isAllChecked()" :indeterminate="hasChecked() && !isAllChecked()"
                  @change="checkedRecursion($event)">
                </el-checkbox>
              </template>
              <template slot-scope="{row}">
                <el-checkbox v-if="row.children" :indeterminate="hasChecked(row) && !isAllChecked(row)"
                  :value="isAllChecked(row)" @change="checkedRecursion($event, row)">
                </el-checkbox>
                <el-checkbox v-else v-model="row.isChecked">
                </el-checkbox>
              </template>
            </el-table-column>
            <el-table-column prop="name" label="菜单名称" min-width="150"></el-table-column>
            <el-table-column width="250">
              <template #header>
                <el-checkbox :disabled="!hasChecked()"
                  :indeterminate="hasChecked(null, true) && !isAllChecked(null, true)" :value="isAllChecked(null, true)"
                  @change="checkedRecursion($event, null, true)" class="_checkbox">全选</el-checkbox>
              </template>
              <template slot-scope="{row}">
                <el-checkbox v-if="row.children" :value="isAllChecked(row, true)" :disabled="!hasChecked(row)"
                  :indeterminate="hasChecked(row, true) && !isAllChecked(row, true)"
                  @change="checkedRecursion($event, row, true)" class="_checkbox">全选
                </el-checkbox>
                <template v-else>
                  <el-checkbox v-for="p in row.permissions" :disabled="!row.isChecked" :key="p.code" class="_checkbox"
                    v-model="p.isChecked">
                    {{ p.name }}
                  </el-checkbox>
                </template>
              </template>
            </el-table-column>

          </el-table>
        </el-form-item>
      </common-form>
      <template #footer>
        <el-button type="primary" @click="save" :loading="$refs.dialog && $refs.dialog.isLoading">保存</el-button>
      </template>
    </common-dialog>
  </div>
</template>
<script>
import commonDialog from "@/components/common/dialog";
import commonForm from "@/components/common/form";
import api from "@/api/sys/role";
import menuApi from "@/api/sys/menu";
// import editMenuList from "./editMenuList";

export default {
  components: { commonDialog, commonForm },
  props: {
    inDialog: {
      type: Boolean,
      default: false
    }
  },
  data() {
    let roleNameExistValidator = (rule, value, callback) => {
      api.checkExistByName(value, this.data.id).then(res => {
        if (res.data) {
          callback("角色名已存在");
        } else {
          callback();
        }
      })
    };
    return {
      data: {
        id: 0,
        name: "",
        remarks: "",
        menuPermissions: []
      },
      title: "",
      isSaved: false,
      //菜单权限原始数据
      menuPermissionData: [],
      //菜单权限树型数据
      menuPermissionTreeData: [],
      menuPermissionLoading: false,
      rules: {
        name: [{ required: true, message: "请填写角色名称" }, { validator: roleNameExistValidator, trigger: "blur" }]
      }
    };
  },
  methods: {
    async initBaseData() {
      this.menuPermissionLoading = true;
      let res = await menuApi.getMenuPermissionList();
      res.data.forEach(item => {
        item.isChecked = false;
        item.permissions.forEach(i => i.isChecked = false)
      });
      this.menuPermissionData = res.data;
      this.menuPermissionTreeData = this.$commonJs.toTreeData(res.data);
      this.menuPermissionLoading = false;
    },
    async showCreate() {
      this.title = "创建角色";
      await this.$refs.dialog.show();
    },
    async showEditById(id) {
      this.$refs.dialog.loading(true);
      this.title = "编辑角色";
      await this.$refs.dialog.show();
      let res = await api.getEditById(id)
      this.data = res.data;
      this.setMenuPermissionData(res.data.menuPermissions);
      this.$refs.dialog.loading(false);
    },
    onClose() {
      if (this.isSaved) {
        this.$emit("close-saved");
      }
    },
    //窗口关闭后
    onClosed() {
      this.title = "";
      this.isSaved = false;
      this.$refs.form.reset();
      this.resetMenuPermissionData();
    },
    //设置菜单权限值
    setMenuPermissionData(data) {
      data.forEach(item => {
        var d = this.menuPermissionData.find(i => i.id == item.menuId);
        if (d != null) {
          d.isChecked = true;
          d.permissions.forEach(i => i.isChecked = item.permissionCodes.includes(i.code))
        }
      })
    },
    resetMenuPermissionData() {
      let _reset = function (data) {
        data.forEach(item => {
          item.isChecked = false;
          item.permissions.forEach(i => i.isChecked = false)
          if (item.children) {
            _reset(item.children);
          }
        });
      };
      _reset(this.menuPermissionData);
    },
    //菜单权限是否全部勾选
    isAllChecked(row, isPermission = false) {
      let children = row ? row.children : this.menuPermissionTreeData;
      children = children && children.filter(i => (i.permissions && i.permissions.length > 0) || (i.row && i.row.length > 0));
      return children.length > 0 && children.every(item => {
        if (item.children) {
          return this.isAllChecked(item, isPermission);
        } else {
          if (isPermission) {
            return item.permissions.every(i => i.isChecked);
          } else {
            return item.isChecked;
          }
        }
      })
    },
    //菜单权限是否有一个勾选
    hasChecked(row, isPermission = false) {
      let children = row ? row.children : this.menuPermissionTreeData;
      return children && children.some(item => {
        if (item.children) {
          return this.hasChecked(item, isPermission);
        } else {
          if (isPermission) {
            return item.permissions.some(i => i.isChecked);
          } else {
            return item.isChecked;
          }
        }
      })
    },
    //递归勾选
    checkedRecursion(checked, row, isPermission = false) {
      let children = row ? row.children : this.menuPermissionTreeData;
      children && children.forEach(item => {
        if (item.children) {
          this.checkedRecursion(checked, item, isPermission);
        } else {
          if (isPermission) {
            item.permissions.forEach(i => i.isChecked = checked)
          } else {
            item.isChecked = checked;
          }
        }
      });
    },
    //保存
    async save() {
      this.$refs.dialog.loading();
      var valid = await this.$refs.form.validate();
      if (!valid) {
        this.$refs.dialog.loading(false);
        return;
      }
      var checkedMenuPermissions = this.menuPermissionData.filter(i => i.isChecked);
      let saveData = this.data;
      saveData.menuPermissions = checkedMenuPermissions.map(item => {
        return {
          menuId: item.id,
          permissionCodes: item.permissions.filter(i => i.isChecked).map(i => i.code)
        }
      })
      let res = await api.save(saveData);
      if (res.code != 0) {
        this.$refs.dialog.loading(false);
        return;
      }
      this.$message.success("保存成功");
      this.data.id = res.data;
      this.isSaved = true;
      this.$refs.dialog.loading(false);
    }
  }
};
</script>
<style lang="scss">
._checkbox {
  margin-right: 10px;

  .el-checkbox__label {
    padding-left: 6px;
    font-size: 12px;
  }
}
</style>